/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ucmconfchecker.UI;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.picking.PickedInfo;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.renderers.VertexLabelRenderer;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;
import org.jfree.util.ShapeUtilities;
import ucmconfchecker.conformance.Edge;
import ucmconfchecker.conformance.EventTrace;
import ucmconfchecker.conformance.Report;
import ucmconfchecker.conformance.Scenario;
import ucmconfchecker.pArchitecture.Responsibility;
import ucmconfchecker.ucmrender.UCMFlabotLayout;

/**
 *
 * @author Administrador
 */
public class ScenarioView<T> extends javax.swing.JPanel {

    

    /**
     * Creates new form ScenarioView
     */
    protected Map<T,Number> transparency = new HashMap<T,Number>();
    protected Set<T> seedVertices = new HashSet<T>();
    
    private Layout<T,Edge> defaultLayout;
    private Layout<T,Edge> precedenceLayout;
    private Layout<T,Edge> layout;
    private Scenario<T> g;
    private EventTrace<T> trace;
    
    private Report<T> report;
    
    public static JDialog showDialog(JFrame owner,Scenario graph){
         JDialog dialog = new JDialog(owner,"Scenario");	
        ScenarioView eventView = new ScenarioView();
        eventView.setGraph(graph);
        dialog.getContentPane().add(eventView, BorderLayout.CENTER);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        dialog.setBounds(50, 50, 800, 400);
        dialog.setVisible(true);
        eventView.update();
        return dialog;
    }
    public static JDialog showDialog(ApplicationView owner, Scenario scenario, Layout layout) {
        JDialog dialog = new JDialog(owner,"Scenario");	
        ScenarioView eventView = new ScenarioView();
        eventView.setGraphLayout(layout);
        eventView.setGraph(scenario);
        dialog.getContentPane().add(eventView, BorderLayout.CENTER);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        dialog.setBounds(50, 50, 800, 400);
        dialog.setVisible(true);
        eventView.update();
        return dialog;
    }
    
    public ScenarioView() {
        initComponents();
    }

    public void setGraph(Scenario<T> graph){
        this.g = graph;
        update();
    }
    public void setTrace(EventTrace<T> trace){
        this.trace = trace;
        if(g!=null)
            update();
    }
    
    public void update(){
        if (g==null)
            return;
        
        VisualizationViewer<T,Edge> vv = new VisualizationViewer<T,Edge>(getLayout(g));
        
        PickedState<T> pickedState = vv.getPickedVertexState();
//        vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Edge>(vv.getPickedEdgeState(), Color.black, Color.red));
//        vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<T>(vv.getPickedVertexState(), 
//                Color.red, Color.yellow));
        vv.setBackground(Color.white);
        
        // add a listener for ToolTips
        vv.setVertexToolTipTransformer(new ToStringLabeller());
//        PickedState<Integer> picked_state = vv.getPickedVertexState();
        //        affineTransformer = vv.getLayoutTransformer();
        //        Predicate<Context<edu.uci.ics.jung.graph.Graph<Integer,Number>,Number>> self_loop = new SelfLoopEdgePredicate<Integer,Number>();
        //         create decorators
        //        seedFillColor = new SeedFillColor<Integer>(pickedState);
        //        seedDrawColor = new SeedDrawColor<Integer>(pickedState);
        EdgeWeightStrokeFunction<T> ewcs = new EdgeWeightStrokeFunction<T>(g,report);
        //        vsh = new VertexStrokeHighlight<Integer,Number>(g, picked_state);
//        VertexFontTransformer<T> vff = new VertexFontTransformer<T>();
//        eff = new EdgeFontTransformer<Number>();
//        vs_none = new ConstantTransformer(null);
//        es_none = new ConstantTransformer(null);
//        vssa = new VertexShapeSizeAspect<Integer,Number>(g, voltages);
//        show_edge = new DirectionDisplayPredicate<Integer,Number>(true, true);
//        show_arrow = new DirectionDisplayPredicate<Integer,Number>(true, false);
//        show_vertex = new VertexDisplayPredicate<Integer,Number>(false);
//
//        // uses a gradient edge if unpicked, otherwise uses picked selection
//        edgeDrawPaint = 
//            new GradientPickedEdgePaintFunction<Integer,Number>(
//                    new PickableEdgePaintTransformer<Number>(
//                            vv.getPickedEdgeState(),Color.black,Color.cyan), vv);
//        edgeFillPaint = 
//            new GradientPickedEdgePaintFunction<Integer,Number>(
//                    new PickableEdgePaintTransformer<Number>(
//                            vv.getPickedEdgeState(),Color.black,Color.cyan), vv);
//        
        vv.getRenderContext().setVertexFillPaintTransformer(new SeedFillColor<T>(pickedState,report));
        vv.getRenderContext().setVertexDrawPaintTransformer(new SeedDrawColor<T>(pickedState,report));
        vv.getRenderContext().setVertexStrokeTransformer(new VertexStrokeHighlight<T,Edge>(g, pickedState,report));
        vv.setVertexToolTipTransformer(new ToStringLabeller());
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
//        vv.getRenderContext().setLabelOffset(-20);
//        vv.getRenderContext().setVertexFontTransformer(vff);
//        vv.getRenderContext().setVertexIncludePredicate(show_vertex);
//        
        vv.getRenderContext().setEdgeDrawPaintTransformer( new EdgeColorFunction<T>(g,report) );
        vv.getRenderContext().setEdgeLabelTransformer(new ConstantTransformer(null));
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.N);
//        vv.getRenderContext().setEdgeFontTransformer(eff);
        vv.getRenderContext().setEdgeStrokeTransformer(ewcs);
//        vv.getRenderContext().setEdgeIncludePredicate(show_edge);
        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<T,Edge>());
//        vv.getRenderContext().setEdgeArrowPredicate(show_arrow);
//        
        vv.getRenderContext().setArrowFillPaintTransformer(new EdgeColorFunction<T>(g,report));
         vv.getRenderContext().setArrowDrawPaintTransformer(new EdgeColorFunction<T>(g,report));
        
         if(defaultLayout!=null && !precedenceToggleButton.isSelected()){
            //dibujo de componentes
             vv.addPreRenderPaintable(new ComponentDraw<T>(vv,(UCMFlabotLayout)defaultLayout));

            //forma de las activaciones
            Transformer<T, Shape> vertexShape = new VertexShapeTransformer<T>();
            vv.getRenderContext().setVertexShapeTransformer(vertexShape);
         }
        
        final DefaultModalGraphMouse<T,Edge> graphMouse = new DefaultModalGraphMouse<T,Edge>();
        graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
        vv.setGraphMouse(graphMouse);
        
        JPanel jp = new JPanel();
        jp.setLayout(new BorderLayout());
        
//        vv.setBackground(Color.white);
        GraphZoomScrollPane scrollPane = new GraphZoomScrollPane(vv);
        
//        jp.add(scrollPane);
       
//        gm = new DefaultModalGraphMouse<Integer, Number>();
//        vv.setGraphMouse(gm);
//        gm.add(new PopupGraphMousePlugin());

//        addBottomControls( jp );
//        vssa.setScaling(true);

//        vv.setVertexToolTipTransformer(new VoltageTips<Number>());
        vv.setToolTipText("<html><center>Use the mouse wheel to zoom<p>Click and Drag the mouse on a node to move it.<p>Ctrl+click on a node to center the view on it.</p></html>");
//          graphPanel.add(jp, BorderLayout.CENTER);

//            JFrame frame = new JFrame("MeetNow!");	
//            JPanel chartPanel = jp;
//            frame.getContentPane().add(chartPanel, BorderLayout.CENTER);
//            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//            frame.setBounds(50, 50, 800, 200);
//            frame.setVisible(true);
            graphPanel.removeAll();
            
            graphPanel.setLayout(new BorderLayout());
            graphPanel.add(scrollPane, BorderLayout.CENTER);
//        return jp;
    }

    void setReport(Report<T> report) {
        this.report=report;
        update();
    }

    public void setGraphLayout(Layout<T,Edge> layout) {
        this.defaultLayout = layout;
    }
    private final static class EdgeWeightStrokeFunction<V> extends ScenarioTransformer<V> implements Transformer<Edge,Stroke>
    {
        protected static final Stroke basic = new BasicStroke(1);

        
        protected boolean weighted = true;
        
        public EdgeWeightStrokeFunction(Scenario<V> scenario, Report<V> report)
        {
            this.report = report;
            this.graph = scenario;
        }
        
        public void setWeighted(boolean weighted)
        {
            this.weighted = weighted;
        }
        
        public Stroke transform(Edge e)
        {
            if (weighted)
            {   
                if(report!=null){
                    if(report.getMissingEventConflicts().contains(graph.getTarget(e))
                     ||report.getMissingEventConflicts().contains(graph.getSource(e))) {
                        return dotted;
                    }
                }else{
                    return basic;
                }
            }
            return basic;
        }
        
    }
    private final static class EdgeColorFunction<V> extends ScenarioTransformer<V> implements Transformer<Edge,Paint>
    {
        protected static final Stroke basic = new BasicStroke(1);

        
        protected boolean weighted = true;
        
        public EdgeColorFunction(Scenario<V> scenario, Report<V> report)
        {
            this.report = report;
            this.graph = scenario;
        }
        
        public void setWeighted(boolean weighted)
        {
            this.weighted = weighted;
        }
        
        public Paint transform(Edge e)
        {
            if (weighted)
            {   
                if(report!=null){
                    if(report.getMissingEventConflicts().contains(graph.getSource(e)) ||
                       report.getMissingEventConflicts().contains(graph.getTarget(e))) {
                        return COLOR_ERROR;
                    }else if(report.getPrecedenceConflicts().containsKey(graph.getTarget(e))) {
                        if(report.getPrecedenceConflicts().get(graph.getTarget(e)).equals(graph.getSource(e))){
                            return COLOR_PRECEDENCE;
                        }
                    }
                }
            }
            return COLOR_DEFAULT;
        }
        
    }
    private abstract static class ScenarioTransformer<V> {
        float[] dotting = {1.0f, 3.0f};
        float[] dashing = {5.0f};
        
        protected static Color COLOR_SELECTED =new Color(0, 0, 1, 1.0f);
        protected static Color COLOR_MISSING =new Color(1, 1, 1, 1.0f);
        protected static Color COLOR_DEFAULT =new Color(0, 0, 0, 1.0f);
        protected static Color COLOR_ERROR =new Color(1, 0, 0, 1.0f);
        protected static Color COLOR_OK =new Color(0, 1, 0, 1.0f);
        protected static Color COLOR_PRECEDENCE =new Color(1, 1, 0, 1.0f);
        
        protected boolean highlight = false;
        protected Stroke heavy = new BasicStroke(5);
        protected Stroke medium = new BasicStroke(3);
        protected Stroke light = new BasicStroke(1);
        protected Stroke dotted = new BasicStroke(1.0f,
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, dotting, 0f);
        Stroke dashed = new BasicStroke(1.0f,
            BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, dashing, 0f);
        protected PickedInfo<V> pi;
        protected Scenario<V> graph;
        
        protected Report<V> report;
        
    }
    private final static class VertexStrokeHighlight<V,E> extends ScenarioTransformer<V> implements
    Transformer<V,Stroke>
    {        
        public VertexStrokeHighlight(Scenario<V> graph, PickedInfo<V> pi, Report<V> report)
        {
            this.graph = graph;
            this.pi = pi;
            this.report = report;
        }
        
        public void setHighlight(boolean highlight)
        {
            this.highlight = highlight;
        }
        
        public Stroke transform(V v)
        {
            if (highlight)
            {
               
                if (pi.isPicked(v)){
                    return heavy;
                }else{
                    for(V w : graph.getNeighbors(v)) {
//                    for (Iterator iter = graph.getNeighbors(v)v.getNeighbors().iterator(); iter.hasNext(); )
//                    {
//                        Vertex w = (Vertex)iter.next();
                        if (pi.isPicked(w))
                            return medium;
                    }
                    return light;
                }
            }
            if(report!=null && !report.getWithoutConflict().contains(v)){
                    return dotted;
                }
            else
                return light; 
        }

    }
    
    private final static class VertexFontTransformer<V> 
    	implements Transformer<V,Font>
    {
        protected boolean bold = false;
        Font f = new Font("Helvetica", Font.PLAIN, 20);
        Font b = new Font("Helvetica", Font.BOLD, 20);
        
        public void setBold(boolean bold)
        {
            this.bold = bold;
        }
        
        public Font transform(V v)
        {
            if (bold)
                return b;
            else
                return f;
        }
    }

    private static class VertexShapeTransformer<T> implements Transformer<T, Shape>{

         private final Shape[] styles = { 
            ShapeUtilities.createDiagonalCross(8, 2),
            new Rectangle(-20, -10, 40, 20),
            new Ellipse2D.Double(-25, -10, 50, 20),
            new Arc2D.Double(-30, -15, 60, 30, 30, 30, 
                Arc2D.PIE) };

        @Override
        public Shape transform(T i) {
            return styles[0];
        }
    }
private final class SeedDrawColor<V> extends ScenarioTransformer<V> implements Transformer<V,Paint> 
    {
        protected PickedInfo<V> pi;
        protected final static float dark_value = 0.8f;
        protected final static float light_value = 0.2f;
        protected boolean seed_coloring;
        
        public SeedDrawColor(PickedInfo<V> pi, Report<V> report)
        {
            this.pi = pi;
            seed_coloring = false;
            this.report = report;
        }

        public void setSeedColoring(boolean b)
        {
            this.seed_coloring = b;
        }
        
        public Paint transform(V v)
        {
            
            if(report!=null && !report.getWithoutConflict().contains(v)){
                if(report.getMissingPreconditionConflicts().containsKey(v)) {
                    return Color.BLACK;
                }else
                    return COLOR_ERROR;
            }
            return Color.BLACK;
        }
        
//        public Paint getFillPaint(V v)
//        {
//            float alpha = transparency.get(v).floatValue();
//            if (pi.isPicked(v))
//            {
//                return new Color(1f, 1f, 0, alpha); 
//            }
//            else
//            {
//                if (seed_coloring && seedVertices.contains(v))
//                {
//                    Color dark = new Color(0, 0, dark_value, alpha);
//                    Color light = new Color(0, 0, light_value, alpha);
//                    return new GradientPaint( 0, 0, dark, 10, 0, light, true);
//                }
//                else
//                    return new Color(1f, 0, 0, alpha);
//            }
//                
//        }
    }
    
    private final class SeedFillColor<V> extends ScenarioTransformer<V> implements Transformer<V,Paint>
    {
        protected PickedInfo<V> pi;
        protected final static float dark_value = 0.8f;
        protected final static float light_value = 0.2f;
        protected boolean seed_coloring;
        
        public SeedFillColor(PickedInfo<V> pi,Report<V> report)
        {
            this.pi = pi;
            seed_coloring = true;
            this.report=report;
        }

        public void setSeedColoring(boolean b)
        {
            this.seed_coloring = b;
        }
        
//        public Paint getDrawPaint(V v)
//        {
//            return Color.BLACK;
//        }
        
        public Paint transform(V v)
        {   Number transparencyValue = transparency.get(v);
            float alpha=1.0f;
            if(transparencyValue!=null)
                alpha = transparency.get(v).floatValue();
            if (pi.isPicked(v))
            {
                return COLOR_SELECTED; 
            }
            else if(report!=null){
                if(!report.getWithoutConflict().contains(v)){
                    if(report.getMissingEventConflicts().contains(v)) {
                        return COLOR_MISSING;
                    }else if(report.getPrecedenceConflicts().containsKey(v)) {
                        return COLOR_PRECEDENCE;
                    }else if(report.getMissingPreconditionConflicts().containsKey(v)) {
                        return COLOR_OK;
                    }
                    else{
                        return COLOR_ERROR;
                    }
                }else{
                    return COLOR_OK;
                }
            }else
            {
                if (seed_coloring && seedVertices.contains(v))
                {
                    Color dark = new Color(0, 0, dark_value, alpha);
                    Color light = new Color(0, 0, light_value, alpha);
                    return new GradientPaint( 0, 0, dark, 10, 0, light, true);
                }
                else
                    return COLOR_DEFAULT;
            }
                
        }
    }
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jToolBar1 = new javax.swing.JToolBar();
        precedenceToggleButton = new javax.swing.JToggleButton();
        graphPanel = new javax.swing.JPanel();

        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        precedenceToggleButton.setText("Precedence Layout");
        precedenceToggleButton.setFocusable(false);
        precedenceToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        precedenceToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        precedenceToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                precedenceToggleButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(precedenceToggleButton);

        javax.swing.GroupLayout graphPanelLayout = new javax.swing.GroupLayout(graphPanel);
        graphPanel.setLayout(graphPanelLayout);
        graphPanelLayout.setHorizontalGroup(
            graphPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        graphPanelLayout.setVerticalGroup(
            graphPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 269, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
            .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
        if(layout!=null)
            layout.setSize(this.getSize());
    }//GEN-LAST:event_formComponentResized

    private void precedenceToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_precedenceToggleButtonActionPerformed
        update();
    }//GEN-LAST:event_precedenceToggleButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel graphPanel;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JToggleButton precedenceToggleButton;
    // End of variables declaration//GEN-END:variables
    
    public Layout<T,Edge> getLayout(Scenario<T> scenario){
//        Layout<T,Edge> layout = new FRLayout<T,Edge>(g);
//        layout.setGraph(g);
//        int count = g.getVertices().size();
//        
//        Map<T,Integer> index;
////        if(trace!=null){
////             index = g.getIndexes(trace);
////        }else{
//            index = g.getIndexes();
////        }
//        Map<Integer,Integer> rows = new HashMap<Integer,Integer>();
//
//        for(T v: g.getVertices()){
//            int column = index.get(v);
//            
//            Integer row = rows.get(column);
//            if(row == null){
//                row = 1;
//            }
//            rows.put(column, row+1);
//            boolean sourceSink=false;
//            if(g.getPredecessorCount(v)>1 || g.getSuccessorCount(v)>1){
//                sourceSink=true;
//            }
//            double step = 2;
//            int x = this.getSize().width*column/count;
//            int y = (int) (this.getSize().height/step/4+(int)(this.getSize().height/step/4*((column%2)))+(int) (this.getSize().height/step/2*((row%2))));
//            if(sourceSink){
//                y+=this.getSize().height/(step*2);
//            }
//            layout.setLocation(v, new Point.Double(x,y));
////            System.out.println("Position: "+v+" ("+x+","+y+")::("+column+","+row+")");
//            layout.lock(v, true);
//        }
//        return layout;

        if(defaultLayout!=null && !precedenceToggleButton.isSelected()){
            layout = defaultLayout;
        }else{
            if(precedenceLayout==null){
                precedenceLayout= new PrecedenceLayout<T>(g);
            }layout = precedenceLayout;
        }
        if(graphPanel.getSize()!=null){
            layout.setSize(graphPanel.getSize());
        }
        return layout;
    }
    
    private static class ComponentDraw<T> implements VisualizationViewer.Paintable{
        private final UCMFlabotLayout flabotLayout;
        private final VisualizationViewer<T,Edge> vv;
        
        public ComponentDraw(VisualizationViewer<T,Edge> vv,UCMFlabotLayout flabotLayout){
            this.flabotLayout = flabotLayout;
            this.vv = vv;
        }
            public void paint(Graphics g) {
                    Graphics2D g2d = (Graphics2D)g;                   
                    AffineTransform oldXform = g2d.getTransform();
                    AffineTransform lat = 
                    	vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getTransform();
                    AffineTransform vat = 
                    	vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getTransform();
                    AffineTransform at = new AffineTransform();
                    at.concatenate(g2d.getTransform());
                    at.concatenate(vat);
                    at.concatenate(lat);
                    g2d.setTransform(at);
//                    g.drawImage(icon.getImage(), 0, 0,
//                    		icon.getIconWidth(),icon.getIconHeight(),vv);
                    if(flabotLayout.getComponents()!=null){
                        for(ucmconfchecker.pArchitecture.Component component: flabotLayout.getComponents()){
//                            g2d.setColor(Color.black);
                            g2d.setStroke(new BasicStroke(3F));
                            Point2D position = flabotLayout.getPosition(component);
                            Dimension dimensions = flabotLayout.getDimensions(component);
                            g2d.setColor(Color.GRAY);
                            g2d.drawRect((int)position.getX(), (int)position.getY(), dimensions.width, dimensions.height);
                            g2d.drawString(component.getName(), (int)position.getX(), (int)position.getY()-3);
                            g2d.setStroke(new BasicStroke(2F));
                            g2d.setColor(Color.black);
                            g2d.drawRect((int)position.getX()+dimensions.width-40, (int)position.getY()+10, 30, 30);
                            g2d.drawRect((int)position.getX()+dimensions.width-50, (int)position.getY()+15, 20, 7);
                            g2d.drawRect((int)position.getX()+dimensions.width-50, (int)position.getY()+27, 20, 7);
                        }
                    }
                    g2d.setTransform(oldXform);
            }
            public boolean useTransform() { return false; }
       
    }
}
